const DEFAULT_MODEL = 'openrouter/llama-3.1-8b-instruct';

export class OpenRouterClient {
    constructor(config = {}) {
        this.baseUrl = config.baseUrl || 'https://openrouter.ai/api/v1';
        this.apiKey = config.apiKey || '';
        this.model = config.model || DEFAULT_MODEL;
        this.appUrl = config.appUrl || 'https://pg-zdm.local';
        this.appTitle = config.appTitle || 'PG-ZDM Shopping Assistant';
        this.defaultParams = config.defaultParams || { temperature: 0.7 }; // 可按需扩展
    }

    updateConfig(config = {}) {
        if (config.apiKey !== undefined) {
            this.apiKey = config.apiKey;
        }
        if (config.model) {
            this.model = config.model;
        }
        if (config.baseUrl) {
            this.baseUrl = config.baseUrl;
        }
        if (config.appUrl) {
            this.appUrl = config.appUrl;
        }
        if (config.appTitle) {
            this.appTitle = config.appTitle;
        }
        if (config.defaultParams) {
            this.defaultParams = { ...this.defaultParams, ...config.defaultParams };
        }
    }

    async *streamChat(messages, params = {}) {
        if (!this.apiKey) {
            throw new Error('缺少 OpenRouter API Key');
        }

        if (typeof chrome !== 'undefined' && chrome.runtime?.connect) {
            try {
                for await (const chunk of this.#streamViaBackground(messages, params)) {
                    yield chunk;
                }
                return;
            } catch (error) {
                console.warn('[OpenRouter] 背景流式失败，尝试直接请求:', error);
            }
        }

        for await (const chunk of this.#streamDirect(messages, params)) {
            yield chunk;
        }
    }

    async *#streamDirect(messages, params = {}) {
        const response = await fetch(`${this.baseUrl}/chat/completions`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${this.apiKey}`,
                'HTTP-Referer': this.appUrl,
                'X-Title': this.appTitle
            },
            body: JSON.stringify({
                model: this.model || DEFAULT_MODEL,
                messages,
                stream: true,
                ...this.defaultParams,
                ...params
            })
        });

        if (!response.ok) {
            let errorDetail = `${response.status}`;
            try {
                const errorBody = await response.json();
                errorDetail = errorBody?.error?.message || JSON.stringify(errorBody);
            } catch (err) {
                errorDetail = await response.text();
            }
            throw new Error(`OpenRouter 请求失败: ${errorDetail}`);
        }

        if (!response.body) {
            const text = await response.text();
            if (text) {
                yield text;
            }
            return;
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder('utf-8');
        let buffer = '';

        try {
            while (true) {
                const { value, done } = await reader.read();
                if (done) {
                    break;
                }
                buffer += decoder.decode(value, { stream: true });
                const lines = buffer.split('\n');
                buffer = lines.pop() || '';

                yield* this.#parseLines(lines);
            }

            if (buffer) {
                yield* this.#parseLines([buffer]);
            }
        } finally {
            reader.releaseLock();
        }
    }

    async *#streamViaBackground(messages, params = {}) {
        const port = chrome.runtime.connect({ name: 'openrouter-stream' });

        const payload = {
            baseUrl: this.baseUrl,
            apiKey: this.apiKey,
            model: this.model || DEFAULT_MODEL,
            messages,
            params: { ...this.defaultParams, ...params },
            appUrl: this.appUrl,
            appTitle: this.appTitle
        };

        const queue = [];
        let resolver;
        let finished = false;

        const enqueue = (item) => {
            queue.push(item);
            if (resolver) {
                resolver();
                resolver = null;
            }
        };

        const handleMessage = (message) => {
            switch (message?.type) {
                case 'chunk':
                    enqueue({ value: message.data });
                    break;
                case 'error':
                    enqueue({ error: message.error });
                    finished = true;
                    break;
                case 'end':
                    enqueue({ done: true });
                    finished = true;
                    break;
                default:
                    break;
            }
        };

        port.onMessage.addListener(handleMessage);
        port.onDisconnect.addListener(() => {
            if (!finished) {
                enqueue({ error: '后台连接已断开' });
            }
        });

        port.postMessage({ type: 'start', payload });

        try {
            while (true) {
                if (!queue.length) {
                    await new Promise((resolve) => {
                        resolver = resolve;
                    });
                    continue;
                }

                const item = queue.shift();
                if (item.error) {
                    throw new Error(item.error);
                }
                if (item.done) {
                    break;
                }
                if (item.value) {
                    yield item.value;
                }
            }
        } finally {
            port.onMessage.removeListener(handleMessage);
            try {
                port.disconnect();
            } catch (_) {
                // ignore
            }
        }
    }

    *#parseLines(lines) {
        for (const rawLine of lines) {
            const line = rawLine.trim();
            if (!line || !line.startsWith('data:')) {
                continue;
            }

            const data = line.slice(5).trim();
            if (!data || data === '[DONE]') {
                continue;
            }

            try {
                const parsed = JSON.parse(data);
                const delta = parsed?.choices?.[0]?.delta;
                if (delta?.content) {
                    yield delta.content;
                }
            } catch (err) {
                console.warn('解析 OpenRouter 流式数据失败:', err, line);
            }
        }
    }
}

export { DEFAULT_MODEL };
